package com.yxw.bamboo.core.send.event.mysql;

import com.yxw.bamboo.core.BytesHelper;
import com.yxw.bamboo.core.database.BytesConvert;
import com.yxw.bamboo.core.database.mysql.MySqlConfig;
import com.yxw.bamboo.core.NetPortForward;
import com.yxw.bamboo.core.SocketChannel;
import com.yxw.bamboo.core.database.sql.Mock;
import com.yxw.bamboo.core.database.sql.MockData;
import com.yxw.bamboo.core.send.event.EventArgs;
import com.yxw.bamboo.core.send.event.SendEvent;
import com.yxw.bamboo.core.send.event.mssql.MsSqlDefaultBeforeSendEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Component
public class MySqlDefaultBeforeSendEvent implements SendEvent {

    private final static Logger logger = LoggerFactory.getLogger(MySqlDefaultBeforeSendEvent.class);
    private static final int CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x00200000;
    //mysql固定解析器
    @Autowired @Qualifier("mysqlBytesConvert")
    BytesConvert bytesConvert;
    @Override
    public void process(Object eventSource, EventArgs eventArgs) throws Exception {

        NetPortForward netPortForward=(NetPortForward)eventSource;
        SocketChannel channel=netPortForward.getChannel();
        byte[] des=(byte[])eventArgs.getArg();
        String[] sqlPWDPluginNames= MySqlConfig.getMySqlPwdPlugin();


        if(channel.getChannelName().equals(SocketChannel.LOCAL_TO_REMOTE))
        {
            if(channel.getSocketStep()>=1)
            {
                if(channel.getSocketStep()==1)
                {
                    bytesConvert.getSqlDbAndUserName(des,channel.getSocketHashCode(),sqlPWDPluginNames,channel);
                }else if(channel.getSocketStep()==2)
                {
                    //密码加密减去头部
                    int pwdBytesLength=des.length-4;
                    //密码加密后长度
                    int pwdLength=1;
                    if((channel.getDbINfo().getServerCapabilities() & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA)!= 0)
                    {
                         pwdLength=BytesHelper.writeFieldLength(pwdBytesLength);
                    }

                    //需要去掉头和尾部的0 byte
                    int dbNameIndex=pwdBytesLength+pwdLength+1;
                    int dbNameLength=channel.getDbINfo().getDbNameBytes().length-dbNameIndex-1;
                    byte[] dbNameBytes=new byte[dbNameLength];
                    //channel.getDbINfo().setDbNameBytes();
                    System.arraycopy(channel.getDbINfo().getDbNameBytes(), dbNameIndex, dbNameBytes, 0, dbNameLength);
                    String data=new String(dbNameBytes);
                    channel.getDbINfo().setDbName(data);
                }else
                {
                    byte[] onlyStringBytes=new byte[des.length-5];
                    System.arraycopy(des, 5, onlyStringBytes, 0, onlyStringBytes.length);
                    String data=new String(onlyStringBytes);
                    MockData mockData=Mock.hit(data,channel.getDbINfo().getUserName(),channel.getDbINfo().getDbName());
                    if(mockData!=null)
                    {
                        byte[] expByte=mockData.getReplaceSql().getBytes();
                        byte[] newSendByte=new byte[expByte.length+5];
                        System.arraycopy(des, 0, newSendByte, 0, 5);
                        System.arraycopy(expByte, 0, newSendByte, 5, expByte.length);
                        BytesHelper.writeLongInt(newSendByte,expByte.length+1,0);
                        String sendData=new String(newSendByte);
                        logger.info(channel.getSocketHashCode()+"命中---新发送的sql："+sendData);
                        eventArgs.setResult(newSendByte);
                    }else
                    {
                        logger.info(channel.getSocketHashCode()+"---"+data);
                    }
                }

            }
        }else //
        {
            if(channel.getSocketStep()==1)
            {
                 byte[] noHeaderBytes=new byte[des.length-4];
                System.arraycopy(des, 4, noHeaderBytes, 0, noHeaderBytes.length);
                 int serverCapabilities= bytesConvert.getServerCapabilities(noHeaderBytes);
                 channel.getDbINfo().setServerCapabilities(serverCapabilities);
            }
        }
    }
}
